package com.weixing.mall.provider.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weixing.mall.base.constant.GlobalConstant;
import com.weixing.mall.base.enums.IdGenTagEnum;
import com.weixing.mall.base.orm.MPage;
import com.weixing.mall.base.enums.WhetherEnum;
import com.weixing.mall.core.utils.CommonUtil;
import com.weixing.mall.leaf.api.service.IdGenServiceRpc;
import com.weixing.mall.provider.api.model.dto.MemberAgentBindDto;
import com.weixing.mall.provider.api.model.enums.InOrOutEnum;
import com.weixing.mall.provider.api.model.vo.AgentMemberVo;
import com.weixing.mall.provider.api.model.vo.AgentRpcVo;
import com.weixing.mall.provider.api.model.vo.MemberRpcVo;
import com.weixing.mall.provider.api.service.AgentServiceRpc;
import com.weixing.mall.provider.api.service.BaseSetRPC;
import com.weixing.mall.provider.api.service.GoodsFeign;
import com.weixing.mall.provider.api.service.OrderServiceRpc;
import com.weixing.mall.provider.mapper.MemberMapper;
import com.weixing.mall.provider.model.domain.Member;
import com.weixing.mall.provider.model.domain.MemberPoint;
import com.weixing.mall.provider.model.dto.*;
import com.weixing.mall.provider.model.enums.MemberPointEnum;
import com.weixing.mall.provider.model.query.MemberBindQuery;
import com.weixing.mall.provider.model.query.MemberQuery;
import com.weixing.mall.provider.model.vo.MemberBindVo;
import com.weixing.mall.provider.model.vo.MemberIndexVo;
import com.weixing.mall.provider.model.vo.MemberListVo;
import com.weixing.mall.provider.model.vo.MemberVo;
import com.weixing.mall.provider.service.IMemberPointService;
import com.weixing.mall.provider.service.IMemberService;
import com.weixing.mall.redis.RedissonLocker;
import jodd.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 会员模块-会员表 服务实现类
 * </p>
 *
 * @author Small
 * @since 2019-11-13
 */
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements IMemberService {

    @Autowired
    private IdGenServiceRpc idGenServiceRpc;
    @Autowired
    private AgentServiceRpc agentServiceRpc;
    @Autowired
    private GoodsFeign goodsFeign;
    @Autowired
    private OrderServiceRpc orderServiceRpc;

    @Autowired
    private IMemberPointService memberPointService;
    @Autowired
    private RedissonLocker redissonLocker;
    @Autowired
    private BaseSetRPC baseSetRPC;
    @Autowired
    private IMemberService memberService;

    @Override
    public IPage<MemberBindVo> memberBindlist(Page page, MemberBindQuery memberBindQuery) {
        return baseMapper.memberBindlist(page, memberBindQuery);
    }

    @Override
    public MemberRpcVo selectByIdMemberRpcVo(Long id) {

        return baseMapper.selectByIdMemberRpcVo(id);
    }

    @Override
    public MemberIndexVo selectMemberIndex(Long mid) {

        MemberIndexVo memberIndexVo = new MemberIndexVo();


        MemberVo member = baseMapper.selectDetail(mid);
        int myPoints = member.getAccumPoint();
        boolean isAgent = member.getIsAgent().equals(WhetherEnum.YES.getValue());//推荐人和
        //我的收藏
        int myStore = goodsFeign.selectMyGoodsStore(mid);
        //int myStore = 1;
        //我的足迹
        int myHistory = goodsFeign.selectMyGoodsHistory(mid);


        int waitPay = orderServiceRpc.getCountfrontOrder(mid, 1);
        int cancell = orderServiceRpc.getCountfrontOrder(mid, 2);
        int waitSend = orderServiceRpc.getCountfrontOrder(mid, 3);
        int waitRecieve = orderServiceRpc.getCountfrontOrder(mid, 4);
        int finish = orderServiceRpc.getCountfrontOrder(mid, 5);
        int afterSale = orderServiceRpc.getCountfrontOrder(mid, 6);

        memberIndexVo.setMyPoints(myPoints);
        memberIndexVo.setMyStore(myStore);
        memberIndexVo.setMyHistory(myHistory);
        memberIndexVo.setWaitPay(waitPay);
        memberIndexVo.setCancell(cancell);
        memberIndexVo.setWaitSend(waitSend);
        memberIndexVo.setWaitRecieve(waitRecieve);
        memberIndexVo.setFinish(finish);
        memberIndexVo.setAfterSale(afterSale);
        memberIndexVo.setMember(member);
        memberIndexVo.setAgent(isAgent);
        return memberIndexVo;
    }

    @Override
    public void bindDel(Long id) {
        baseMapper.BinDel(id);
    }


    @Override
    public Member selectByOpenId(String openId) {
        return getOne(new QueryWrapper<Member>().eq("openid", openId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unBindAgent(Long mid) {
        Member member = getById(mid);
        member.setAgentId(null);
        member.setAgentSn(null);
        member.setAgentName(null);
        member.setAgentBindTime(null);
        updateById(member);
    }

    @Override
    public void saveOrUpdateMember(MemberAgentBindDto bindDto) {
        Member member = selectByMobile(bindDto.getMobile());
        if (member == null) {
            member = new Member();
            member.setPassword(CommonUtil.encryptPassword(bindDto.getPassword()));
            long memberNo = idGenServiceRpc.segmentKey(IdGenTagEnum.MEMBER_NO.getValue());
            member.setMemberNo("lm_" + memberNo);
            member.setNickName(bindDto.getAgentName());
        }
        member.setAgentBindTime(new Date());
        member.setIsDel(WhetherEnum.NO.getValue());
        member.setRegisterTime(new Date());
        member.setIsAgent(WhetherEnum.YES.getValue());
        member.setAgentId(bindDto.getAgentId());
        member.setAgentName(bindDto.getAgentName());
        member.setAgentSn(bindDto.getAgentSn());
        member.setAgentRoleBindId(bindDto.getAgentId());
        member.setIsEnable(WhetherEnum.YES.getValue());
        member.setMobile(bindDto.getMobile());
        member.setRevision(0);
        if (null == member.getId()) {
            save(member);
        } else {
            updateById(member);
        }
    }

    @Override
    public void changAgentStatus(long agentId) {
        AgentRpcVo vo = agentServiceRpc.selectByAgentId(agentId).getData();
        Member member = selectByMobile(vo.getMobile());
        if (null != member) {
            baseMapper.unAgent(vo.getMobile());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handlerPoint(Long memberId, Integer point, Integer inOrOut, String desp) {
        Member member = baseMapper.selectById(memberId);
        Member updateMemer = new Member();
        updateMemer.setId(memberId);
        if (inOrOut.equals(MemberPointEnum.IN.getValue())) {
            updateMemer.setAccumPoint(member.getAccumPoint() + point);
        } else {
            updateMemer.setAccumPoint(member.getAccumPoint() - point);
        }
        MemberPoint memberPoint = new MemberPoint();
        memberPoint.setAfterNum(member.getAccumPoint());
        memberPoint.setBeferNum(updateMemer.getAccumPoint());
        memberPoint.setCount(point.longValue());
        memberPoint.setMemberName(member.getNickName());
        memberPoint.setInOrOut(inOrOut);
        memberPoint.setDesp(desp);
        memberPointService.save(memberPoint);
        baseMapper.update(member, new QueryWrapper<Member>().eq("id", memberId).eq("revision", member.getRevision()));
    }

    @Override
    public Member selectByMobile(String mobile) {
        QueryWrapper<Member> queryWrapper = new QueryWrapper<Member>().eq("mobile", mobile);
        return getOne(queryWrapper);
    }

    @Override
    public boolean checkMobileExist(String mobile) {
        return null == selectByMobile(mobile) ? false : true;
    }

    @Override
    public void register(RegisterDto registerDto, Long agentId) {
        Member member = new Member();
        // 生成会员编码
        long memberNo = idGenServiceRpc.segmentKey(IdGenTagEnum.MEMBER_NO.getValue());
        member.setMemberNo("lm_" + memberNo);
        member.setMobile(registerDto.getMobile());
        String moblie=registerDto.getMobile();
        member.setNickName(moblie.substring(moblie.length()-6,moblie.length()));
        member.setPassword(CommonUtil.encryptPassword(registerDto.getPassword()));
        member.setAgentId(agentId);
        save(member);
        if(member.getId() != null){
            memberService.bonusPointsHandle(member.getId(),GlobalConstant.REG_POINT,null,null);
        }
    }

    @Override
    public void resetPwd(String mobile, String password) {
        Member member = selectByMobile(mobile);
        Member member1 = new Member();
        member1.setId(member.getId());
        member1.setPassword(CommonUtil.encryptPassword(password));
        updateById(member1);
    }


    @Override
    public MemberVo selectDetail(long id) {
        return baseMapper.selectDetail(id);
    }

    @Override
    public void updateAvator(String avator, Long mid) {
        Member member = new Member();
        member.setId(mid);
        member.setAvator(avator);
        updateById(member);
    }

    @Override
    public void updateBirthDay(String birthDay, Long mid) {
        Member member = new Member();
        member.setId(mid);
        member.setBirthDay(birthDay);
        updateById(member);
    }

    @Override
    public void updateGender(int gender, Long mid) {
        Member member = new Member();
        member.setId(mid);
        member.setGender(gender);
        updateById(member);
    }

    @Override
    public void updateMobile(String mobile, Long mid) {
        Member member = new Member();
        member.setId(mid);
        member.setMobile(mobile);
        updateById(member);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProvincesPath(MemberLocDto memberLoc, Long mid) {
        Member member = getById(mid);
        member.setProvince(memberLoc.getProvince());
        member.setProvinceCode(memberLoc.getProvinceCode());
        member.setCity(memberLoc.getCity());
        member.setCityCode(memberLoc.getCityCode());
        member.setArea(memberLoc.getArea());
        member.setAreaCode(memberLoc.getAreaCode());
        updateById(member);
    }

    @Override
    public void updatePassword(Long id, String newPwd) {
        Member member = new Member();
        member.setId(id);
        member.setPassword(newPwd);
        updateById(member);
    }

    @Override
    public IPage<MemberListVo> selectListOfPage(Page page, MemberQuery memberQuery) {
        return baseMapper.selectListOfPage(page, memberQuery);
    }

    @Override
    public void create(MemberDto memberDto) {
        Member member = new Member();
        BeanUtils.copyProperties(memberDto, member);
        member.setIsEnable(memberDto.getIsEnable().getValue());
        member.setGender(memberDto.getGender().getValue());
        member.setMemberRank(memberDto.getMemberRank().getValue());
        if (null == memberDto.getId()) {
            long memberNo = idGenServiceRpc.segmentKey(IdGenTagEnum.MEMBER_NO.getValue());
            member.setMemberNo("lm_" + memberNo);
            member.setPassword(CommonUtil.encryptPassword(memberDto.getPassword()));
            save(member);
        } else {
            if (StringUtil.isNotEmpty(memberDto.getPassword())) {
                member.setPassword(CommonUtil.encryptPassword(memberDto.getPassword()));
            }
            updateById(member);
        }
    }

    @Override
    public MPage<AgentMemberVo> selectAgentMemberOfPage(MPage page, long agentId) {
        return baseMapper.selectAgentMemberOfPage(page, agentId);
    }

    @Override
    public void bindCustomer(BinCustomerDto binCustomerDto) {
        Member member = new Member();
        member.setId(binCustomerDto.getMemberId());
        member.setKefuId(binCustomerDto.getCustomerId());
        member.setKefuBindTime(new Date());
        member.setKefuName(binCustomerDto.getCustomerName());
        updateById(member);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean handlerPoint(Long memberId, Long point, Integer inOrOut, String desp, Long operatorId) {
        boolean flag = false;
        boolean lockFlag = redissonLocker.tryLock("point:"+memberId, TimeUnit.SECONDS,10,10);
        if(!lockFlag){
            return false;
        }
        try {
            if(memberId == null || point == null || inOrOut == null){
                return false;
            }
            Member member = getById(memberId);
            if(ObjectUtil.isEmpty(member)){
                return false;
            }
            long oldAccumPoint = member.getAccumPoint();
            long newAccumPoint = 0L;
            if(MemberPointEnum.IN.getValue().equals(inOrOut)){
                newAccumPoint = oldAccumPoint + point;
            }else if(MemberPointEnum.OUT.getValue().equals(inOrOut) && oldAccumPoint >= point){
                newAccumPoint = oldAccumPoint - point;
            }else{
                return false;
            }
            member.setAccumPoint(newAccumPoint);
            flag = update(member,new QueryWrapper<Member>().eq("id", memberId).eq("revision", member.getRevision()));
            if(flag){
                MemberPointDto memberPointDto = new MemberPointDto();
                memberPointDto.setMemberId(memberId);
                memberPointDto.setAfterNum(newAccumPoint);
                memberPointDto.setBeferNum(oldAccumPoint);
                memberPointDto.setCount(point);
                memberPointDto.setMemberName(member.getNickName());
                memberPointDto.setInOrOut(inOrOut);
                memberPointDto.setDesp(desp);
                memberPointDto.setCreatedBy(operatorId);
                memberPointService.addMemberPoint(memberPointDto);
            }
        }catch (Exception e){
           e.printStackTrace();
        }finally {
            redissonLocker.unlock("point:"+memberId);
        }
        return flag;
    }

    @Override
    public void bonusPointsHandle(Long memberId, String code, BigDecimal amount, Long operatorId) {
        if(memberId != null && StrUtil.isNotEmpty(code)){
            Long bonusPoint = 0L;
            String desp = "";
            BigDecimal value = baseSetRPC.getValueByCode(code);
            switch (code){
                case GlobalConstant.REG_POINT:
                    bonusPoint = value.longValue();
                    desp = "注册奖励";
                break;
                case GlobalConstant.BUY_POINT:
                    if(amount != null && value != null){
                        bonusPoint = amount.multiply(value).longValue();
                    }
                    desp = "下单奖励";
                break;
                case GlobalConstant.SHOW_POINT:
                    bonusPoint = value.longValue();
                    desp = "上传买家秀奖励";
                break;
            }
            if(bonusPoint != 0L){
                handlerPoint(memberId,bonusPoint, InOrOutEnum.IN.getValue(),desp,operatorId);
            }
        }

    }

    @Override
    public Member loadUserByXcxOpenId(String openId) {

        return getOne(new QueryWrapper<Member>().eq("xcxopenid", openId));
    }

    @Override
    public void register(String openId, String mobile) {
        Member member = new Member();
        // 生成会员编码
        long memberNo = idGenServiceRpc.segmentKey(IdGenTagEnum.MEMBER_NO.getValue());
        member.setMemberNo("lm_" + memberNo);
        member.setMobile(mobile);
        String substring = mobile.substring(mobile.length() - 6, mobile.length());
        member.setNickName(substring);
        member.setPassword(CommonUtil.encryptPassword(substring));
        member.setXcxopenid(openId);
        save(member);
        if(member.getId() != null){
            memberService.bonusPointsHandle(member.getId(),GlobalConstant.REG_POINT,null,null);
        }
    }

    @Override
    public void updateCid(String cid, Long mid) {
        Member member = new Member();
        member.setId(mid);
        member.setCid(cid);
        updateById(member);
    }

    @Override
    public List<String> loadAgentCid(String[] agentIds){
        return baseMapper.loadAgentCid(agentIds);
    }

    @Override
    public String loadAgentCid(Long agentId) {
        return baseMapper.getAgentCid(agentId);
    }
}
